package web

import (
	"fmt"
	"gitee.com/xiao_hange/go-admin-pkg/pkg/ginx"
	regexp "github.com/dlclark/regexp2"
	"github.com/gin-gonic/gin"
	"go-admin/server/internal/domain"
	"go-admin/server/internal/service"
	"go-admin/server/internal/web/form"
	"go-admin/server/internal/web/jwt"
	"go-admin/server/internal/web/middleware"
	"go-admin/server/utils"
	"net/http"
)

type AdminHandler struct {
	svc         service.AdminServer
	emailExp    *regexp.Regexp
	passwordExp *regexp.Regexp
	smsScv      service.CodeService
	jwt.Handler
}

func NewAdminHandler(svc service.AdminServer, jwtHal jwt.Handler, sms service.CodeService) *AdminHandler {
	const (
		emailRegexPattern = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"
	)
	emailExp := regexp.MustCompile(emailRegexPattern, regexp.None)
	return &AdminHandler{
		svc:      svc,
		Handler:  jwtHal,
		emailExp: emailExp,
		smsScv:   sms,
	}
}

func (a *AdminHandler) RegisterRoutes(server *gin.Engine) {
	ug := server.Group("/admin")

	ug.POST("/login", ginx.WrapBody[form.LoginReq](a.login))
	ug.POST("/login-out", a.loginOut)

	ug.GET("/admin-lst", a.adminLst)
	ug.GET("/admin-info", a.adminInfo)

	ug.PUT("/update-password", a.updatePassword)
	ug.PUT("/create-admin", a.createAdmin)
	ug.PUT("/update-admin", a.updateAdmin)
	ug.PUT("/update-status", a.updateStatus)
	ug.PUT("/send-sms", a.sendSms)
}

func (a *AdminHandler) login(ctx *gin.Context, req form.LoginReq) ginx.Result {
	err := utils.Verify(req, utils.LoginVerify)
	if err != nil {
		return ginx.Result{Code: http.StatusNoContent, Msg: err.Error()}
	}
	admin, err := a.svc.Login(ctx.Request.Context(), req.Account, req.Password)

	if err == service.ErrInvalidUserOrPassword {
		return ginx.Result{Code: http.StatusNoContent, Msg: "用户名密码不对"}
	}
	if err != nil {
		return ginx.Result{Code: http.StatusNoContent, Msg: "系统错误"}
	}

	token, err := a.SetJwtTokenForAdmin(ctx, admin)
	if err != nil {
		return ginx.Result{Code: http.StatusNoContent, Msg: "系统错误"}
	}
	ResultMap := make(map[string]interface{})
	ResultMap["token"] = token

	return ginx.Result{Code: http.StatusOK, Msg: "登录成功", Data: ResultMap}
}

func (a *AdminHandler) loginOut(ctx *gin.Context) {
	err := a.ClearToken(ctx, middleware.JwtAdmin.AdminID)
	if err != nil {
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "退出成功！", nil)
	return
}

func (a *AdminHandler) adminLst(ctx *gin.Context) {
	var req form.PageInfo
	err := ctx.Bind(&req)
	if err != nil {
		return
	}
	list, total, err := a.svc.GetAdminLst(ctx.Request.Context(), domain.PageInfo{
		Page:      req.Page,
		Limit:     req.Limit,
		Mobile:    req.Mobile,
		LoginName: req.LoginName,
	})
	RenderJSONPage(ctx, http.StatusOK, http.StatusOK, "ok！", list, total)
	return
}

func (a *AdminHandler) adminInfo(ctx *gin.Context) {
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "ok", middleware.JwtAdmin)
}

func (a *AdminHandler) updatePassword(ctx *gin.Context) {
	var req form.UpdatePasswordReq
	err := ctx.Bind(&req)
	if err != nil {
		return
	}

	err = utils.Verify(req, utils.UpdatePasswordVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	if req.ConfirmPassword != req.NewPassword {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "两次输入的密码不一致", nil)
		return
	}
	err = a.svc.UpdatePassword(ctx.Request.Context(), middleware.JwtAdmin.AdminID, req.NewPassword)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "修改失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "修改成功", nil)
	return
}

func (a *AdminHandler) createAdmin(ctx *gin.Context) {
	var req form.AdminData
	err := ctx.Bind(&req)
	if err != nil {
		return
	}
	err = utils.Verify(req, utils.AdminVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = utils.Verify(req, utils.AdminPasswordVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	ok, err := a.emailExp.MatchString(req.Email)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "内部错误", nil)
		return
	}
	if !ok {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "邮箱格式不正确！", nil)
		return
	}

	err = a.svc.CreateAdmin(ctx.Request.Context(), domain.Admin{
		Email:         req.Email,
		Mobile:        req.Mobile,
		Password:      req.Password,
		LoginName:     req.LoginName,
		AdminName:     req.AdminName,
		HeadSculpture: req.HeadSculpture,
		RoleIds:       req.RoleIds,
	})
	switch err {
	case nil:
		RenderJSON(ctx, http.StatusOK, http.StatusOK, "添加成功", nil)
		return
	case service.ErrAdminDuplicate:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "该手机号、邮箱、登录名已存在", nil)
		return
	default:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "添加失败", nil)
		return
	}
}

func (a *AdminHandler) updateAdmin(ctx *gin.Context) {
	var req form.AdminData
	err := ctx.Bind(&req)
	if err != nil {
		return
	}
	err = utils.Verify(req, utils.AdminVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = utils.Verify(req, utils.AdminIDVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	ok, err := a.emailExp.MatchString(req.Email)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "内部错误", nil)
		return
	}
	if !ok {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "邮箱格式不正确！", nil)
		return
	}
	err = a.svc.UpdateAdmin(ctx.Request.Context(), req.AdminId, domain.Admin{
		Email:         req.Email,
		Mobile:        req.Mobile,
		Password:      req.Password,
		LoginName:     req.LoginName,
		AdminName:     req.AdminName,
		HeadSculpture: req.HeadSculpture,
		RoleIds:       req.RoleIds,
	})
	switch err {
	case nil:
		RenderJSON(ctx, http.StatusOK, http.StatusOK, "修改成功", nil)
		return
	case service.ErrAdminDuplicate:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "该手机号、邮箱、登录名已存在", nil)
		return
	default:
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "修改失败", nil)
		return
	}
}

func (a *AdminHandler) updateStatus(ctx *gin.Context) {
	var req form.AdminStatus
	err := ctx.Bind(&req)
	if err != nil {
		return
	}
	err = utils.Verify(req, utils.AdminStatusVerify)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, err.Error(), nil)
		return
	}
	err = a.svc.UpdateStatus(ctx.Request.Context(), req.AdminId, req.Status)
	if err != nil {
		RenderJSON(ctx, http.StatusOK, http.StatusNoContent, "操作失败", nil)
		return
	}
	RenderJSON(ctx, http.StatusOK, http.StatusOK, "操作成功", nil)
	return
}

func (a *AdminHandler) sendSms(ctx *gin.Context) {
	err := a.smsScv.Send(ctx.Request.Context(), "login", "15300050629")
	fmt.Println(err)
	switch err {
	case nil:
		ctx.JSON(http.StatusOK, Result{
			Msg: "发送成功",
		})
	case service.ErrCodeSendTooMany:
		ctx.JSON(http.StatusOK, Result{
			Msg: "发送太频繁请稍后再试",
		})
	case service.ErrRateLimit:
		ctx.JSON(http.StatusOK, Result{
			Msg: "限流了",
		})
	default:
		ctx.JSON(http.StatusOK, Result{
			Code: 5,
			Msg:  "系统错误",
			Data: err.Error(),
		})
	}
}
